/****************************************************************************
**
** Copyright (C) 2010 Mist Poryvaev.
** All rights reserved.
** Contact: Mist Poryvaev (mist.poryvaev@gmail.com)
**
** This file is part of the SOTA project.
**
****************************************************************************/

#ifndef SOTA_PRIVATE_H
#define SOTA_PRIVATE_H

#include <QtCore>
#include <QtNetwork>
#include <QtTest/QSignalSpy>

namespace sota_Private_Namespace // private internal namespace
{

class SotaSender : public QObject
{
	Q_OBJECT
public:
	static bool qt_connect(QObject * _sender, const char * _signal, const char * _receiver, const char * _slot, int _flags = 0);
	static bool qt_disconnect(QObject * _sender, const char * _signal, const char * _receiver, const char * _slot);
private slots:
	void genericSlot(); // universal slot for any connected signal
	void writeQueue(); // slot for writing data when connection established
private:
	struct Data; Data * d;
	explicit SotaSender(QObject * _sender, const char * _signal, const char * _receiver, const char * _slot, int _flags = 0);
	~SotaSender();
};

// --------------------------------

class SotaSocket : public QObject
{
	Q_OBJECT
public:
	explicit SotaSocket(QTcpSocket * _tcp_socket);
	~SotaSocket();
	QByteArray & buffer(); // accumulator for received data
	QHostAddress peerAddress() const; // address of remote machine
	void clear(qint64 _count = -1);
	int newDataSize() const; // new data size in buffer
private:
	struct Data; Data * d;
signals:
	void readyRead(SotaSocket *);
private slots:
	void on_socket_readyRead();
};

class SotaReceiver;
class SotaServer: public QObject
{
	Q_OBJECT
public:
	static void registerReceiver(SotaReceiver * _sota_receiver, quint16 port); // registers receiver in list
	static void unregisterReceiver(SotaReceiver * _sota_receiver, quint16 port); // unregisters receiver from list
	static bool isListening(quint16 _port); // checks server state
private slots:
	void on_server_newConnection(); // slot for new connection
	void on_socket_readyRead(SotaSocket * _sota_socket); // slot for new data; note: this slot is DIRECTLY connected to SotaSocket::readyRead signal
private:
	struct Data; Data * d;
	explicit SotaServer();
	~SotaServer();
};

class SotaReceiver : public QObject
{
	Q_OBJECT
public:
	bool isServerListening() const; // checks server state
	void invoke(const QByteArray & _data, const QByteArray & _peerAddress); // invokes method of connected object
	static QHostAddress caller_address();
	static bool qt_connect(const char * _sender, const char * _signal, QObject * _receiver, const char * _slot);
	static bool qt_disconnect(const char * _sender, const char * _signal, QObject * _receiver, const char * _slot);
private:
	struct Data; Data * d;
	explicit SotaReceiver(const char * _sender, const char * _signal, QObject * _receiver, const char * _slot);
	~SotaReceiver();
};

} // end of private namespace


#endif // SOTA_PRIVATE_H
